package controller

import (
	"RocFamilySystem/internal/service"
	"RocFamilySystem/models"
	"RocFamilySystem/pkg/constant"
	"RocFamilySystem/tools/container"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"log"
	"net/http"
	"reflect"
	"runtime"
	"strconv"
	"strings"
)

// 路由注册容器
var registerContainer = make(map[string]any)

// 用于注册权限容器
var permissionContainer = make(map[string]models.SysPermission)

func registerPermissionContainer(remark, name, url, method string) {
	permission := models.SysPermission{
		Remark: &remark,
		Name:   &name,
		Url:    &url,
		Method: &method,
	}
	permissionContainer[name] = permission
}

// InitController 初始化路由
func InitController() {
	engine, _ := container.GetBeanContainer("gin.Engine")
	for key, val := range registerContainer {
		service, _ := container.GetBeanContainer("service." + strings.ReplaceAll(key, "Controller", "Service"))
		v := reflect.ValueOf(val)
		//设置服务
		v.MethodByName("SetService").Call([]reflect.Value{reflect.ValueOf(service)})
		//注册路由
		v.MethodByName("RegisterRouter").Call([]reflect.Value{reflect.ValueOf(engine)})
		//注册到容器中
		container.PushContainer(val)
	}

	//获取权限service
	permissionService := container.GetBeanFromContainer("service.SysPermissionService").(*service.SysPermissionService)
	//需要手动减一
	list := permissionService.QuerySysPermission(nil, 1-1, 999999).List.([]models.SysPermission)

	//先将内容放到map中
	dbPermissionMap := make(map[string]models.SysPermission)
	for _, ele := range list {
		dbPermissionMap[*ele.Name] = ele
	}

	//判断应用容器中的权限和数据库中的是否匹配
	removeIds := make([]string, 0)
	for key, val := range dbPermissionMap {
		//如果存在则删除两个容器中记录值
		_, ok := permissionContainer[key]
		if ok {
			//存在，则删除两个的记录
			delete(permissionContainer, key)
			delete(dbPermissionMap, key)
		} else {
			//不存在则需要删除
			removeIds = append(removeIds, fmt.Sprint(*val.Id))
		}
	}

	//两个都删除之后，dbPermissionMap剩余的就是要删除的权限，permissionContainer剩余的是要追加的
	//1.删除多余的权限
	if len(removeIds) != 0 {
		permissionService.RemoveSysPermissionBatch(removeIds)
		db := container.GetBeanFromContainer("gorm.DB").(*gorm.DB)
		db.Exec("delete from sys_role_permissions where sys_permission_id in (?)", removeIds)
	}
	//2.批量添加新的权限
	permissionList := make([]models.SysPermission, 0)
	for _, permission := range permissionContainer {
		permissionList = append(permissionList, permission)
	}
	if len(permissionList) != 0 {
		permissionService.BatchAddSysPermission(permissionList)
	}
}

// RegisterInterface 注册结构体
type RegisterInterface interface {
	RegisterRouter(engine *gin.Engine)
	GetPageInfo(ctx *gin.Context) (int, int) //获取分页信息
	GetLoginUserId(ctx *gin.Context) int     //获取登录用户
	//GetLoginUser(ctx *gin.Context) *models.SysUser //获取登录用户
}

// BaseController 基础控制器
type BaseController struct {
	RegisterInterface
}

// Result 返回结构体
type Result struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Data any    `json:"data"`
}

// HandleError 处理错误
func (c *BaseController) HandleError(err error, msg string) {
	_, file, line, _ := runtime.Caller(1)
	if err != nil {
		fmt.Printf("%s:%d\t%s", file, line, err.Error())
		log.Println("内部错误：" + err.Error())
		log.Panicln(msg)
	}
}

// GetPageInfo 获取分页信息
func (c *BaseController) GetPageInfo(ctx *gin.Context) (pageNum, pageSize int) {
	var err error
	pageNum, err = strconv.Atoi(ctx.Query("pageNum"))
	if err != nil {
		pageNum = 1
	}
	pageNum--
	pageSize, _ = strconv.Atoi(ctx.Query("pageSize"))
	if err != nil {
		pageSize = 10
	}
	return
}

// GetLoginUserId 获取登录用户ID
func (c *BaseController) GetLoginUserId(ctx *gin.Context) int {
	loginUserId, _ := ctx.Get(constant.REQUEST_CONTEXT_LOGIN_USER_ID)
	convertId, _ := strconv.Atoi(loginUserId.(string))
	return convertId
}

// FailResult 失败返回
func (c *BaseController) FailResult(ctx *gin.Context, msg string) {
	ctx.JSON(http.StatusOK, Result{
		Code: 500,
		Msg:  msg,
	})
}

// SuccessResult 成功返回
func (c *BaseController) SuccessResult(ctx *gin.Context, data any) {
	ctx.JSON(http.StatusOK, Result{
		Code: 200,
		Msg:  "操作成功",
		Data: data,
	})
}

// CustomResult 自定义返回内容
func (c *BaseController) CustomResult(ctx *gin.Context, code int, msg string, data any) {
	ctx.JSON(http.StatusOK, Result{
		Code: code,
		Msg:  msg,
		Data: data,
	})
}
